home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Programming / Comal / ModuleDev / IoWindow.c < prev    next >
C/C++ Source or Header  |  2001-04-11  |  14KB  |  516 lines

  1. /************************************************************************/
  2. /*                                                                                                      */
  3. /*                                                                                                      */
  4. /*                                   AmigaCOMAL Interpreter                                     */
  5. /*                                 Input/output window module                           */
  6. /*                                       version 93.01.31                                          */
  7. /*                                                                                                      */
  8. /*                                                                                                      */
  9. /************************************************************************/
  10.  
  11. #include <exec/types.h>
  12. #include <exec/io.h>
  13. #include <exec/memory.h>
  14. #include <exec/ports.h>
  15. #include <exec/memory.h>
  16. #include <intuition/intuition.h>
  17. #include <devices/conunit.h>
  18. #include <proto/exec.h>
  19. #include <proto/intuition.h>
  20. #include <proto/graphics.h>
  21. #include <proto/layers.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include "Comal.h"
  27. #include "Comal_protos.h"
  28.  
  29. extern struct ComalStruc *ComalStruc;
  30.  
  31. static unsigned char SetCurStr[] = {0x9B,0,0,0,0x3B,0,0,0,0x48,0};
  32. static LONG SetCurStrLen = 9;
  33. static unsigned char CurOffStr[] = {0x9B,0x30,0x20,0x70,0};
  34. static LONG CurOffStrLen = 4;
  35. static unsigned char CurOnStr[] = {0x9B,0x20,0x70,0};
  36. static LONG CurOnStrLen = 3;
  37.  
  38.  
  39. struct KeyBuffer
  40. {
  41.   UBYTE NumBytes;     /* Number of bytes in buffer      */
  42.   UBYTE NextByte;     /* Next byte to read              */
  43.   UBYTE Buffer[30];   /* Key buffer                     */
  44. };
  45.  
  46. struct ConsoleId
  47. {
  48.   struct IOStdReq *OutputMsg;
  49.   struct IOStdReq *InputMsg;
  50.     UBYTE  InputMsgBuf;
  51.     UBYTE  InputSignal;
  52.   struct KeyBuffer KeyBuffer;
  53.   unsigned ConDevOpen:   1;   /* 'console.device' open          */
  54.   unsigned CrtOpen:      1;
  55.   unsigned KbdOpen:      1;
  56.   unsigned CloseReq:     1;   /* Close as soon as possible      */
  57. };
  58.  
  59. static struct Screen *Screen;
  60. static struct Window *Window;
  61. static struct ConsoleId *ConsoleId;
  62.  
  63. static struct NewScreen NewScreen =
  64. {
  65.     0,0,640,256,
  66.     4,            /* Screen depth */
  67.     0,1,
  68.     HIRES | SPRITES,
  69.     CUSTOMSCREEN,
  70.     0,
  71.     "Special IO screen",
  72.     0,0
  73. };
  74.  
  75. static void CloseConsole(void);
  76. static void QueueRead(struct ConsoleId *ConsoleId);
  77. BOOL CrtWrite(ULONG ConId, UBYTE *Data, LONG *NumByte);
  78. static ULONG ReadOneKey(void);
  79.  
  80. /************************************************************************/
  81. /*                                                                      */
  82. /*   Open and close routines for common IO window                       */
  83. /*                                                                      */
  84. /************************************************************************/
  85.  
  86. struct Window *MakeIoWindow(void)
  87. {
  88.   struct NewWindow NewWindow;
  89.  
  90.   if ( Screen = OpenScreen(&NewScreen) )
  91.   {
  92.     NewWindow.LeftEdge = 0;
  93.     NewWindow.TopEdge =12;
  94.     NewWindow.DetailPen = 0;
  95.     NewWindow.BlockPen = 1;
  96.     NewWindow.Title = "Special IO window";
  97.     NewWindow.Flags = WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWSIZING
  98.                       | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH | GIMMEZEROZERO;
  99.     NewWindow.IDCMPFlags = NULL;
  100.     NewWindow.Type = CUSTOMSCREEN;
  101.     NewWindow.Screen = Screen;
  102.     NewWindow.Width = Screen->Width;
  103.     NewWindow.Height = Screen->Height-NewWindow.TopEdge;
  104.     NewWindow.MaxWidth = Screen->Width;
  105.     NewWindow.MaxHeight = Screen->Height;
  106.     NewWindow.FirstGadget = NULL;
  107.     NewWindow.CheckMark = NULL;
  108.     NewWindow.BitMap = NULL;
  109.     NewWindow.MinWidth = 150;
  110.     NewWindow.MinHeight = 75;
  111.     if ( !(Window = OpenWindow(&NewWindow)) )
  112.       CloseScreen(Screen);
  113.   }
  114.   return(Window);
  115. }
  116.  
  117. void RemoveIoWindow(void)
  118. {
  119.   if ( Window )
  120.   {
  121.         CloseWindow(Window);
  122.     Window = NULL;
  123.   }
  124.   if (Screen )
  125.   {
  126.     CloseScreen(Screen);
  127.     Screen = NULL;
  128.   }
  129. }
  130.  
  131. /************************************************************************/
  132. /*                                                                      */
  133. /*   Standard console IO routines                                       */
  134. /*                                                                      */
  135. /************************************************************************/
  136.  
  137. static struct ConsoleId *OpenConsole(void)
  138. {
  139.   struct MsgPort *Port;
  140.  
  141.   if ( !(ConsoleId = (struct ConsoleId *)calloc(1,sizeof(struct ConsoleId))) )
  142.     return(NULL);
  143.   if ( !MakeIoWindow() )
  144.   {
  145.     free((char *)ConsoleId);
  146.     ConsoleId = NULL;
  147.     return(NULL);
  148.   }
  149.  
  150.   if ( !(Port = CreatePort(0,0)) )
  151.   {
  152.     CloseConsole();
  153.     return(NULL);
  154.   }
  155.   if ( !(ConsoleId->InputMsg = CreateStdIO(Port)) )
  156.   {
  157.     DeletePort(Port);
  158.     CloseConsole();
  159.     return(NULL);
  160.   }
  161.   ConsoleId->InputSignal = Port->mp_SigBit;
  162.   if ( !(Port = CreatePort(0,0)) )
  163.   {
  164.     CloseConsole();
  165.     return(NULL);
  166.   }
  167.   if ( !(ConsoleId->OutputMsg = CreateStdIO(Port)) )
  168.   {
  169.     DeletePort(Port);
  170.     CloseConsole();
  171.     return(NULL);
  172.   }
  173.   ConsoleId->OutputMsg->io_Data = (APTR)Window;
  174.   ConsoleId->OutputMsg->io_Length = sizeof(struct Window);
  175.   if ( OpenDevice("console.device",0,(struct IORequest *)ConsoleId->OutputMsg,0) )
  176.   {
  177.     CloseConsole();
  178.     return(NULL);
  179.   }
  180.   ConsoleId->ConDevOpen = 1;
  181.   
  182.   ConsoleId->InputMsg->io_Device = ConsoleId->OutputMsg->io_Device;
  183.   ConsoleId->InputMsg->io_Unit = ConsoleId->OutputMsg->io_Unit;
  184.   CrtWrite((ULONG)ConsoleId,CurOffStr,&CurOffStrLen);
  185.   AddSignal(1 << ConsoleId->InputSignal);
  186.   QueueRead(ConsoleId);
  187.     return(ConsoleId);
  188. }
  189.  
  190. static void CloseConsole(void)
  191. {
  192.     struct MsgPort *Port;
  193.     
  194.     if (ConsoleId->ConDevOpen)
  195.     {
  196.         AbortIO((struct IORequest *)ConsoleId->InputMsg);
  197.         CloseDevice((struct IORequest *)ConsoleId->OutputMsg);
  198.     RemSignal(1 << ConsoleId->InputSignal);
  199.         ConsoleId->ConDevOpen = 0;
  200.     }
  201.     if ( ConsoleId->InputMsg )
  202.     {
  203.         Port = ConsoleId->InputMsg->io_Message.mn_ReplyPort;
  204.         DeleteStdIO(ConsoleId->InputMsg);
  205.         DeletePort(Port);
  206.         ConsoleId->InputMsg = NULL;
  207.     }
  208.     if ( ConsoleId->OutputMsg )
  209.     {
  210.         Port = ConsoleId->OutputMsg->io_Message.mn_ReplyPort;
  211.         DeleteStdIO(ConsoleId->OutputMsg);
  212.         DeletePort(Port);
  213.         ConsoleId->OutputMsg = NULL;
  214.     }
  215.  
  216.   RemoveIoWindow();
  217.  
  218.   free((char *)ConsoleId);
  219.   ConsoleId = NULL;
  220. }
  221.  
  222. ULONG CrtOpen(char *Name,UWORD Mode,short *Status)
  223. {
  224.   if ( ConsoleId == NULL )
  225.     OpenConsole();
  226.   if ( ConsoleId )
  227.   {
  228.     if ( (ComalStruc->Flags & F_TRACEMODE) == 0 )
  229.       WindowToFront(Window);
  230.     ConsoleId->CrtOpen = 1;
  231.   }
  232.   return((ULONG)ConsoleId);
  233. }
  234.  
  235. void CrtClose(ULONG ConId)
  236. {
  237.   ConsoleId->CrtOpen = 0;
  238.   if ( ConsoleId->CloseReq && !ConsoleId->KbdOpen )
  239.     CloseConsole();
  240. }
  241.  
  242. ULONG KbdOpen(char *Name,UWORD Mode,short *Status)
  243. {
  244.   if ( ConsoleId == NULL )
  245.     OpenConsole();
  246.   if ( ConsoleId )
  247.   {
  248.     if ( (ComalStruc->Flags & F_TRACEMODE) == 0 )
  249.       (void)ActivateWindow(Window);
  250.     ConsoleId->KbdOpen = 1;
  251.   }
  252.   return((ULONG)ConsoleId);
  253. }
  254.  
  255. void KbdClose(ULONG ConId)
  256. {
  257.   ConsoleId->KbdOpen = 0;
  258.   if ( ConsoleId->CloseReq && !ConsoleId->CrtOpen )
  259.     CloseConsole();
  260. }
  261.  
  262. /*--------------------------------------------------------------*/
  263. /*                                                                                            */
  264. /*                                         Console IO routines                          */
  265. /*                                                                                            */
  266. /*--------------------------------------------------------------*/
  267.  
  268. static void QueueRead(struct ConsoleId *ConsoleId)
  269. {
  270.     ConsoleId->InputMsg->io_Data = (APTR)(&ConsoleId->InputMsgBuf);
  271.     ConsoleId->InputMsg->io_Length = 1;
  272.     ConsoleId->InputMsg->io_Command = CMD_READ;
  273.     SendIO((struct IORequest *)ConsoleId->InputMsg);
  274. }
  275.  
  276. BOOL CrtWrite(ULONG ConId, UBYTE *Data, LONG *NumByte)
  277. {
  278.   if ( *NumByte )
  279.   {
  280.       ConsoleId->OutputMsg->io_Length = *NumByte;
  281.       ConsoleId->OutputMsg->io_Data = Data;
  282.       ConsoleId->OutputMsg->io_Command = CMD_WRITE;
  283.       DoIO((struct IORequest *)ConsoleId->OutputMsg);
  284.   }
  285.   return(TRUE);
  286. }
  287.  
  288. BOOL CrtWriteLine(ULONG ConId, UBYTE *Line, LONG *NumByte)
  289. {
  290.   if ( *NumByte )
  291.   {
  292.       ConsoleId->OutputMsg->io_Length = *NumByte;
  293.       ConsoleId->OutputMsg->io_Data = Line;
  294.       ConsoleId->OutputMsg->io_Command = CMD_WRITE;
  295.       DoIO((struct IORequest *)ConsoleId->OutputMsg);
  296.   }
  297.     ConsoleId->OutputMsg->io_Length = 1;
  298.     ConsoleId->OutputMsg->io_Data = "\n";
  299.     ConsoleId->OutputMsg->io_Command = CMD_WRITE;
  300.     DoIO((struct IORequest *)ConsoleId->OutputMsg);
  301.   return(TRUE);
  302. }
  303.  
  304. BOOL CrtSetCursor(ULONG ConId, short Row, short Col)
  305. {
  306.   short i;
  307.  
  308.   Row++;
  309.   Col++;
  310.     for (i = 3; i > 0; i--, Row /= 10)
  311.         SetCurStr[i] = (Row % 10)+'0';
  312.     for (i = 7; i > 4; i--, Col /= 10)
  313.         SetCurStr[i] = (Col % 10)+'0';
  314.   CrtWrite(ConId,SetCurStr,&SetCurStrLen);
  315.   return(TRUE);
  316. }
  317.  
  318. BOOL CrtGetCursor(ULONG ConId, short *Row, short *Col)
  319. {
  320.     struct ConUnit *ConsoleUnit;
  321.  
  322.     ConsoleUnit = (struct ConUnit *)(ConsoleId->OutputMsg->io_Unit);
  323.     *Row = ConsoleUnit->cu_YCCP;
  324.     *Col = ConsoleUnit->cu_XCCP;
  325.   return(TRUE);
  326. }
  327.  
  328. short KbdRead(ULONG Id, UBYTE *Buffer, LONG *NumByte, ULONG BreakMask)
  329. {
  330.   struct KeyBuffer *Key;
  331.   UBYTE CharRead;
  332.   
  333.   Key = &ConsoleId->KeyBuffer;
  334.   CharRead = 0;
  335.   while ( CharRead < *NumByte )
  336.   {
  337.     while ( Key->NumBytes == 0 )
  338.     {
  339.       if ( ReadOneKey() & BreakMask )
  340.       {
  341.         *NumByte = CharRead;  /* Return number of bytes actually read   */
  342.         return(0);
  343.       }
  344.       if ( ComalStruc->BreakFlags )
  345.         ExecBreak();
  346.     }
  347.     Buffer[CharRead++] = Key->Buffer[Key->NextByte++];
  348.     Key->NumBytes--;
  349.   }
  350.   *NumByte = CharRead;        /* Return number of bytes actually read   */
  351.   return(0);
  352. }
  353.  
  354. short KbdReadLine(ULONG ConId, UBYTE *Line, LONG *MaxBytes)
  355. {
  356.   struct KeyBuffer *Key;
  357.   LONG Number;
  358.   
  359.   CrtWrite(ConId,CurOnStr,&CurOnStrLen);
  360.   Key = &ConsoleId->KeyBuffer;
  361.   Number = 0;
  362.   do
  363.   {
  364.     Key->NumBytes = 0;
  365.     do
  366.     {
  367.       (void)ReadOneKey();
  368.       if ( ComalStruc->BreakFlags )
  369.       {
  370.         CrtWrite(ConId,CurOffStr,&CurOffStrLen);
  371.         ExecBreak();
  372.         CrtWrite(ConId,CurOnStr,&CurOnStrLen);
  373.       }
  374.     } while ( Key->NumBytes == 0 );
  375.     if ( (Key->Buffer[0] == '\b') && Number )
  376.     {
  377.         ConsoleId->OutputMsg->io_Length = 1;
  378.         ConsoleId->OutputMsg->io_Data = Key->Buffer;
  379.         ConsoleId->OutputMsg->io_Command = CMD_WRITE;
  380.         DoIO((struct IORequest *)ConsoleId->OutputMsg);
  381.       Number--;
  382.     }
  383.     else if ( isprint(Key->Buffer[0]) )
  384.     {
  385.       Line[Number++] = Key->Buffer[0];
  386.         ConsoleId->OutputMsg->io_Length = 1;
  387.         ConsoleId->OutputMsg->io_Data = Key->Buffer;
  388.         ConsoleId->OutputMsg->io_Command = CMD_WRITE;
  389.         DoIO((struct IORequest *)ConsoleId->OutputMsg);
  390.     }
  391.   } while ( (Key->Buffer[0] != '\r') && Number < *MaxBytes );
  392.   *MaxBytes = Number;       /* Return number of bytes actually read     */
  393.   CrtWrite(ConId,CurOffStr,&CurOffStrLen);
  394.   return(0);
  395. }
  396.  
  397. short KbdScan(ULONG Id, UBYTE *Buffer, LONG *NumByte)
  398. {
  399.   struct KeyBuffer *Key;
  400.   
  401.   Key = &ConsoleId->KeyBuffer;
  402.   if ( (Key->NumBytes == 0) && CheckIO((struct IORequest *)ConsoleId->InputMsg) )
  403.     (void)ReadOneKey();
  404.   if ( Key->NumBytes )
  405.   {
  406.     *Buffer = Key->Buffer[Key->NextByte++];
  407.     Key->NumBytes--;
  408.     *NumByte = 1;
  409.   }
  410.   else
  411.     *NumByte = 0;
  412.   return(0);
  413. }
  414.  
  415. static ULONG ReadOneKey(void)
  416. {
  417.   struct KeyBuffer *Key;
  418.     ULONG SignalMask,RetMask;
  419.  
  420.     SignalMask = (1 << ConsoleId->InputSignal);
  421.   Key = &ConsoleId->KeyBuffer;
  422.   Key->NextByte = 0;
  423.   if ( (RetMask = ComalWait(SignalMask)) & SignalMask )
  424.   {
  425.     GetMsg(ConsoleId->InputMsg->io_Message.mn_ReplyPort);
  426.     if ( ConsoleId->InputMsg->io_Actual && (Key->Buffer[Key->NumBytes++] = ConsoleId->InputMsgBuf) == 0x9B )
  427.     {
  428.       do
  429.       {
  430.         QueueRead(ConsoleId);
  431.         RetMask |= ComalWait(SignalMask);
  432.         GetMsg(ConsoleId->InputMsg->io_Message.mn_ReplyPort);
  433.       } while ((Key->Buffer[Key->NumBytes++] = ConsoleId->InputMsgBuf) < 0x40);
  434.     }
  435.     QueueRead(ConsoleId);
  436.   }
  437.   return(RetMask);
  438. }
  439.  
  440. struct Window *IoWindow(void)
  441. {
  442.   return(Window);
  443. }
  444.  
  445. struct IoDevice CrtDevice =
  446. {
  447.   NULL,             /* Next device in list        */
  448.   "ds:",            /* Name of device             */
  449.   CRT_DEVICE,       /* Screen type device         */
  450.   0,                /* Reserved                   */
  451.   &CrtOpen,         /* Open routine               */
  452.   &CrtClose,        /* Close routine              */
  453.   NULL,             /* No read block              */
  454.   &CrtWrite,        /* Write block                */
  455.   NULL,             /* No read line               */
  456.   &CrtWriteLine,    /* Write line                 */
  457.   NULL,             /* No scan routine            */
  458.   &CrtGetCursor,    /* Get cursor                 */
  459.   &CrtSetCursor,    /* Set cursor                 */
  460.   NULL              /* No IO error function       */
  461. };
  462.  
  463. struct IoDevice KbdDevice =
  464. {
  465.   NULL,             /* Next device in list        */
  466.   "kb:",            /* Device name                */
  467.   KBD_DEVICE,       /* Sequential device          */
  468.   0,                /* Reserved                   */
  469.   &KbdOpen,         /* Open routine               */
  470.   &KbdClose,        /* Close routine              */
  471.   &KbdRead,         /* Read block                 */
  472.   &CrtWrite,        /* Write INPUT guide text     */
  473.   &KbdReadLine,     /* Read line                  */
  474.   NULL,             /* No write line              */
  475.   &KbdScan,         /* Scan keyboard              */
  476.   &CrtGetCursor,    /* Get cursor                 */
  477.   &CrtSetCursor,    /* Set cursor                 */
  478.   NULL              /* No IO error function       */
  479. };
  480.  
  481. short ModuleInit(void)
  482. {
  483.     if ( !(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)) )
  484.     return(150);
  485.   else
  486.   {
  487.     AddComalDevice(&KbdDevice);
  488.     AddComalDevice(&CrtDevice);
  489.     return(0);
  490.   }
  491. }
  492.  
  493. void signal(short Signal)
  494. {
  495.   switch ( Signal )
  496.   {
  497.     case SIG_CLEAR:
  498.       if ( ConsoleId ) 
  499.         CloseConsole();
  500.       break;
  501.     case SIG_CLOSE:
  502.     case SIG_DISCARD: 
  503.       if ( ConsoleId ) 
  504.       {
  505.         RemComalDevice(&KbdDevice);
  506.         RemComalDevice(&CrtDevice);
  507.         CloseConsole();
  508.       }
  509.       if( IntuitionBase )
  510.         CloseLibrary((struct Library *)IntuitionBase);
  511.       break;
  512.     default:
  513.       break;
  514.   }
  515. }
  516.